package com.sshtools.view;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JToolBar;
import javax.swing.border.LineBorder;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;

import com.sshtools.view.action.DeployAction;
import com.sshtools.view.action.RestartAction;
import com.sshtools.view.action.StartAction;
import com.sshtools.view.action.StopAction;
import com.sshtools.view.action.SyncAction;
import com.sshtools.view.model.ServerModel;
import com.sshtools.view.model.ServerTableModel;

import tsif.component.log.Log;
import tsif.component.log.Log.LogType;
import tsif.utils.ThreadUtils;

/**
 * 
 * 主视图
 *
 */
public class MainView {

	private final AtomicInteger lockCounter; // 锁定计数器
	private final ExecutorService executor; // 线程池

	// 窗口
	private JFrame frame;

	// 操作列表
	private List<AbstractAction> actionList; // 操作列表

	// 服务器列表
	private ServerTableModel serverTableModel; // 表格数据
	private JTable serverTable;

	// 文本输出
	private JTextArea textArea;

	public MainView() {
		lockCounter = new AtomicInteger();
		executor = Executors.newCachedThreadPool();

		initialize();
	}

	/** 创建操作列表 **/
	private List<AbstractAction> createActionList() {
		List<AbstractAction> list = new ArrayList<>();
		list.add(new StartAction(this, "Start"));
		list.add(new SyncAction(this, "Sync"));
		list.add(new StopAction(this, "Stop"));
		list.add(new RestartAction(this, "Restart"));
		list.add(new DeployAction(this, "Deploy"));
		return list;
	}

	/** 显示窗口 **/
	public void show() {
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setSize(800, 600);
		frame.setVisible(true);
	}

	/** 初始化页面 **/
	private void initialize() {
		frame = new JFrame();
		frame.setBounds(100, 100, 450, 300);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setTitle("ssh");

		// 操作按钮列表
		JToolBar toolBar = new JToolBar();
		toolBar.setFloatable(false);
		frame.getContentPane().add(toolBar, BorderLayout.NORTH);

		// toolBar.addSeparator(); // 间隔

		// 添加任务
		actionList = createActionList();
		int asize = (actionList != null) ? actionList.size() : 0;
		for (int i = 0; i < asize; i++) {
			AbstractAction action = actionList.get(i);
			if (action == null) {
				continue;
			}
			JButton actionBtn = new JButton();
			actionBtn.setEnabled(false);
			actionBtn.setAction(action);
			toolBar.add(actionBtn);

			toolBar.addSeparator(); // 间隔
		}

		// 中部服务器列表视图
		JPanel panel = new JPanel();
		frame.getContentPane().add(panel, BorderLayout.CENTER);
		panel.setLayout(new BorderLayout(0, 0));

		// 列表操作按钮
		JPanel panel_1 = new JPanel();
		panel.add(panel_1, BorderLayout.NORTH);
		panel_1.setLayout(new BoxLayout(panel_1, BoxLayout.X_AXIS));

		JButton allbtn = new JButton("All");
		allbtn.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				serverTableModel.selectAll();
				serverTable.updateUI();
			}
		});
		allbtn.setToolTipText("all select");
		panel_1.add(allbtn);

		JButton nonebtn = new JButton("None");
		nonebtn.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				serverTableModel.unselectAll();
				serverTable.updateUI();
			}
		});
		nonebtn.setToolTipText("none select");
		panel_1.add(nonebtn);

		JButton invertbtn = new JButton("Invert");
		invertbtn.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				serverTableModel.invertSelectedAll();
				serverTable.updateUI();
			}
		});
		invertbtn.setToolTipText("invert selected");
		panel_1.add(invertbtn);

		JSplitPane splitPane = new JSplitPane();
		splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
		panel.add(splitPane, BorderLayout.CENTER);

		// 创建表格列表
		serverTableModel = new ServerTableModel();
		serverTable = new JTable(serverTableModel);
		serverTable.setBorder(new LineBorder(Color.LIGHT_GRAY));
		serverTableModel.addTableModelListener(new TableModelListener() {
			@Override
			public void tableChanged(TableModelEvent event) {
				updateActionBtnState();
			}
		});

		JScrollPane scrollPane1 = new JScrollPane(serverTable);
		splitPane.setLeftComponent(scrollPane1);
		splitPane.setDividerLocation(200);

		// 服务器列表
		// JPopupMenu popupMenu1 = new JPopupMenu();
		// addPopup(scrollPane1, popupMenu1);
		// addPopup(splitPane, popupMenu1);
		// popupMenu1.add("All").addActionListener(new ActionListener() {
		// @Override
		// public void actionPerformed(ActionEvent e) {
		// serverTableModel.selectAll();
		// serverTable.updateUI();
		// }
		// });
		// popupMenu1.add("None").addActionListener(new ActionListener() {
		// @Override
		// public void actionPerformed(ActionEvent e) {
		// serverTableModel.unselectAll();
		// serverTable.updateUI();
		// }
		// });
		// popupMenu1.add("Invert").addActionListener(new ActionListener() {
		// @Override
		// public void actionPerformed(ActionEvent e) {
		// serverTableModel.invertSelectedAll();
		// serverTable.updateUI();
		// }
		// });

		// 下方显示页面
		JPanel panel_3 = new JPanel();
		splitPane.setRightComponent(panel_3);
		panel_3.setLayout(new BorderLayout(0, 0));

		// 滑动条
		JScrollPane scrollPane = new JScrollPane();
		panel_3.add(scrollPane, BorderLayout.CENTER);

		// 文本输出
		textArea = new JTextArea();
		textArea.setAutoscrolls(true);
		textArea.setEditable(false);
		scrollPane.setViewportView(textArea);

		// 文本右键菜单
		JPopupMenu popupMenu = new JPopupMenu();
		addPopup(textArea, popupMenu);
		popupMenu.add("Clean").addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				textArea.setText("");
			}
		});

		// 刷新状态按钮
		updateActionBtnState();

		// 添加绑定日志输出
		Log.setHandler(new ShowMessageListener(textArea));
	}

	/** 添加文本右键菜单 **/
	private static void addPopup(Component component, final JPopupMenu popup) {
		component.addMouseListener(new MouseAdapter() {

			/** 鼠标点击 **/
			public void mousePressed(MouseEvent e) {
				if (e.isPopupTrigger()) {
					showMenu(e);
				}
			}

			/** 鼠标释放 **/
			public void mouseReleased(MouseEvent e) {
				if (e.isPopupTrigger()) {
					showMenu(e);
				}
			}

			/** 显示菜单 **/
			private void showMenu(MouseEvent e) {
				popup.show(e.getComponent(), e.getX(), e.getY());
			}
		});
	}

	/** 锁定操作 **/
	public void lock() {
		lockCounter.incrementAndGet();
		updateActionBtnState();
	}

	/** 解锁操作 **/
	public void unlock() {
		lockCounter.decrementAndGet();
		updateActionBtnState();
	}

	/** 更新操作按钮 **/
	private void updateActionBtnState() {
		boolean isLock = lockCounter.get() > 0;
		boolean isSelected = serverTableModel.getSelectedNum() > 0;
		boolean isEnable = !isLock && isSelected; // 有选择并且没有锁定

		// 遍历刷新操作
		int asize = (actionList != null) ? actionList.size() : 0;
		for (int i = 0; i < asize; i++) {
			AbstractAction action = actionList.get(i);
			action.setEnabled(isEnable);
		}
	}

	public JFrame getFrame() {
		return frame;
	}

	/** 重新加载服务器列表 **/
	public void reloadServers(String filePath) {
		List<ServerModel> serverList = ServerModel.load(filePath);
		if (serverList == null) {
			Log.error("no find server file! " + filePath);
			return;
		}
		serverTableModel.addAll(serverList);
		serverTable.updateUI();
	}

	public ExecutorService getExecutor() {
		return executor;
	}

	/** 基础任务 **/
	public static abstract class ViewBaseAction extends AbstractAction {
		private static final long serialVersionUID = 2472496776801484638L;
		protected MainView mainView;

		public ViewBaseAction(MainView mainView, String name) {
			super(name);
			this.mainView = mainView;
		}
	}

	/** 视图操作按钮 **/
	public static abstract class ViewServerAction extends ViewBaseAction {
		private static final long serialVersionUID = -3357630122981122127L;
		private static final AtomicInteger idCounter = new AtomicInteger();

		public ViewServerAction(MainView mainView, String name) {
			super(mainView, name);
		}

		@Override
		public void actionPerformed(ActionEvent arg0) {
			ExecutorService executor = mainView.getExecutor();
			mainView.lock();
			// 提交任务
			executor.execute(new Runnable() {
				@Override
				public void run() {
					try {
						syncRun();
					} finally {
						mainView.unlock();
					}
				}
			});
		}

		/** 异步运行(不阻塞主线程) **/
		private void syncRun() {
			ExecutorService executor = mainView.getExecutor();
			List<ServerModel> servers = mainView.serverTableModel.getSelectedServers();
			int id = idCounter.incrementAndGet();
			// 执行运行
			if (!beforeRun(id)) {
				return; // 不执行
			}
			// 根据服务器列表执行任务
			try {
				AtomicInteger counter = new AtomicInteger();
				// 遍历服务器, 等待所有任务结束
				for (ServerModel s : servers) {
					Runnable t = createTask(s);
					if (t == null) {
						continue;
					}
					// 判断是否并行执行
					if (!isParallelTask()) {
						t.run(); // 不并行, 直接执行完毕才执行下一个.
						continue;
					}
					// 并行执行任务
					counter.incrementAndGet();
					executor.execute(new Runnable() {
						@Override
						public void run() {
							try {
								t.run();
							} finally {
								counter.decrementAndGet();
							}
						}
					});

				}

				// 等待结束
				while (counter.get() > 0) {
					ThreadUtils.sleep(1000);
				}

			} finally {
				// begin后必须after
				afterRun(id);
			}
		}

		/** 创建任务 **/
		protected abstract Runnable createTask(ServerModel s);

		/** 是否并行执行任务 **/
		public boolean isParallelTask() {
			return true;
		}

		/** 开始运行, 检测参数准备处理等. **/
		protected boolean beforeRun(int id) {
			Log.info("操作开始[" + id + "]: " + this.getValue(Action.NAME));
			return true;
		}

		/** 运行完成 **/
		protected void afterRun(int id) {
			Log.info("操作结束[" + id + "]: " + this.getValue(Action.NAME));
		}
	}

	/** 日志输出 **/
	private static class ShowMessageListener extends Log.ConsoleLogHandler {
		private JTextArea textArea;

		public ShowMessageListener(JTextArea textArea) {
			super(LogType.DEBUG);
			this.textArea = textArea;
		}

		@Override
		public boolean filtr(LogType logtype) {
			return true;
		}

		@Override
		public void writeLog(LogType type, Date time, String threadName, String funcName, String stackTraceStr, Object msg) {
			// 控制台输出
			super.writeLog(type, time, threadName, funcName, stackTraceStr, msg);

			// 格式化
			String typeStr = type.name();
			String showMsg = toString(typeStr, time, threadName, funcName, stackTraceStr, msg);
			// 输出
			textArea.append(showMsg);
			textArea.setCaretPosition(textArea.getText().length());
			textArea.paintImmediately(textArea.getBounds());
		}

		/** 日期格式多线程支持. **/
		private static final ThreadLocal<DateFormat> format = new ThreadLocal<DateFormat>() {
			@Override
			protected DateFormat initialValue() {
				return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			}
		};

		/** 完整字符串输出 **/
		protected static String toString(String type, Date time, String threadName, String funcName, String stackTraceStr, Object msg) {
			StringBuilder strBdr = new StringBuilder();
			strBdr.append(type);
			strBdr.append(" ");
			strBdr.append(format.get().format(time));
			strBdr.append(": ");
			strBdr.append(msg);
			strBdr.append("\r\n");
			return strBdr.toString();
		}
	}

}
